package com.bigdata.schaduler.service;

import com.bigdata.schaduler.client.DolphinClient;
import com.bigdata.schaduler.domain.TaskDefineParam;
import com.bigdata.schaduler.util.Param;
import org.apache.dolphinscheduler.common.enums.HttpMethod;
import org.apache.dolphinscheduler.common.enums.ReleaseState;
import org.apache.dolphinscheduler.dao.entity.TaskDefinition;
import org.apache.dolphinscheduler.plugin.task.api.model.Property;
import org.apache.dolphinscheduler.plugin.task.api.parameters.DependentParameters;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.util.List;

public class TaskDefineService {
  private final DolphinClient dolphinClient;

  public TaskDefineService(DolphinClient dolphinClient) {
    this.dolphinClient = dolphinClient;
  }

  public String getTaskDefinitionUri(Long projectCode) {
    return "projects/" + projectCode + "/task-definition";
  }

  public List<Long> genTaskCodeList(Long projectCode, Integer genNum) {
    String uri = getTaskDefinitionUri(projectCode) + "/gen-task-codes";
    MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
    params.add("genNum", genNum);
    return dolphinClient.requestFormData(HttpMethod.GET, uri, params, List.class);
  }

  public void release(Long projectCode, Long code, ReleaseState releaseState) {
    String uri = getTaskDefinitionUri(projectCode) + "/" + code + "/release?releaseState=" + releaseState.name();
    dolphinClient.requestFormData(HttpMethod.POST, uri, null, Void.class);
  }

  public TaskDefinition create(@Param Long project,
                               @Param Long processDefinitionCode,
                               @Param TaskDefineParam taskDefineParam,
                               @Param(required = false) List<Property> localParams,
                               @Param(required = false) DependentParameters dependentParameters,
                               @Param(required = false) List<String> upstreamCodes) {

    String uri = getTaskDefinitionUri(project) + "/save-single";
    taskDefineParam.setParams(dependentParameters, localParams);
    MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
    params.add("processDefinitionCode", processDefinitionCode);
    params.add("taskDefinitionJsonObj", taskDefineParam);
    if (upstreamCodes != null && !upstreamCodes.isEmpty()) {
      params.add("upstreamCodes", String.join(",", upstreamCodes));
    }
    return dolphinClient.requestFormData(HttpMethod.POST, uri, params, TaskDefinition.class);
  }

  public TaskDefinition update(@Param Long project,
                               @Param Long processDefinitionCode,
                               @Param TaskDefineParam taskDefineParam,
                               @Param(required = false) List<Property> localParams,
                               @Param(required = false) DependentParameters dependentParameters,
                               @Param(required = false) List<String> upstreamCodes) {

    String uri = getTaskDefinitionUri(project) + "/with-upstream";
    taskDefineParam.setParams(dependentParameters, localParams);
    MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
    params.add("processDefinitionCode", processDefinitionCode);
    params.add("taskDefinitionJsonObj", taskDefineParam);
    if (upstreamCodes != null && !upstreamCodes.isEmpty()) {
      params.add("upstreamCodes", String.join(",", upstreamCodes));
    }
    return dolphinClient.requestFormData(HttpMethod.PUT, uri, params, TaskDefinition.class);
  }

  public TaskDefinition select(Long project, Long code) {
    String uri = getTaskDefinitionUri(project) + "/" + code;
    return dolphinClient.requestFormData(HttpMethod.GET, uri, null, TaskDefinition.class);
  }

  public void delete(Long project, Long code) {
    String uri = getTaskDefinitionUri(project) + "/" + code;
    dolphinClient.requestFormData(HttpMethod.DELETE, uri, null, Void.class);
  }
}
